package com.nth.android.util;

import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import android.os.AsyncTask;

public class FileScanner {

    public static interface FileScannerListener {
	public void onFileFound(File file);

	public void onScanCompleted(List<File> files);
    }

    private File file;
    private FilenameFilter filenameFilter;
    private FileScannerListener fileScannerListener;
    private FileScannerTask fileScannerTask;

    public FileScanner(File file, FileScannerListener fileScannerListener) {
	this(file, null, fileScannerListener);
    }

    public FileScanner(File file, FilenameFilter filenameFilter, FileScannerListener fileScannerListener) {
	super();
	this.file = file;
	this.filenameFilter = filenameFilter;
	this.fileScannerListener = fileScannerListener;
    }

    public void scan() {
	fileScannerTask = new FileScannerTask();
	fileScannerTask.execute();
    }

    public void cancel() {
	fileScannerTask.cancel(true);
    }

    private class FileScannerTask extends AsyncTask<Void, File, List<File>> {

	@Override
	protected List<File> doInBackground(Void... params) {
	    return getFiles(file, filenameFilter);
	}

	@Override
	protected void onProgressUpdate(File... values) {
	    super.onProgressUpdate(values);
	    if (fileScannerListener != null) {
		for (File file : values) {
		    fileScannerListener.onFileFound(file);
		}
	    }
	}

	@Override
	protected void onPostExecute(List<File> result) {
	    super.onPostExecute(result);
	    if (fileScannerListener != null) {
		fileScannerListener.onScanCompleted(result);
	    }
	}

	private List<File> getFiles(final File rootDir, final FilenameFilter filenameFilter) {
	    List<File> result = new ArrayList<File>();
	    if (isCancelled()) {
		return result;
	    }

	    final File[] files = rootDir.listFiles(filenameFilter);
	    if (files != null) {
		result.addAll(Arrays.asList(files));
		publishProgress(files);
	    }

	    final File[] dirs = rootDir.listFiles(new FileFilter() {
		@Override
		public boolean accept(File pathname) {
		    return pathname.isDirectory();
		}
	    });
	    if (dirs != null) {
		for (File dir : dirs) {
		    final List<File> deeperList = getFiles(dir, filenameFilter);
		    result.addAll(deeperList);
		}
	    }

	    return result;
	}

    }

}
